package com.intel.utils
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.MorphShape;
	import flash.display.Sprite;
	import flash.display.MovieClip;
	import flash.text.engine.ElementFormat;
	import flash.text.engine.FontDescription;
	import flash.text.engine.TextBlock;
	import flash.text.engine.TextElement;
	import flash.text.engine.TextLine;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	
	/**
	 * ...
	 * @author ...
	 */
	public class TextRender 
	{
		/*
		 * 
		 *	look to make a singlton in the future 
		 * 
		 * 
		
	
		
		
		private static var blnInstanceCreated:Boolean;
		private static var instance:TextRender;
		default culture
		
		
		
		public function () {
			
		}
		*/
		
		private static var strCulture:String = "ar-sa";
		private static var _blnWasInitalised:Boolean;
		private static var arrComplexCultures:Array;
		private static var blnIsComplexCulture:Boolean;
		public static var iBidiLevel:int = 0;
		private static var iVerticalLineSpacer:int = 5;
		private static var iFontIncrease:Number = -2;
		
		private static var RENDERED_LINE:String = "RenderedLine";
		
		public static function initialise(in_culture_id:String):void 
		{			
			_blnWasInitalised = true;
			createCultures();
			
			if(strCulture != "") strCulture = in_culture_id;
			
			var culture:TextCulture;
			
			for each(var cul:TextCulture in arrComplexCultures) 
			{
				if (cul.name == strCulture) {
					culture = cul;
					break;
				}
			}
			
			if (culture == null) {
				// dont need the bidi
				blnIsComplexCulture = false;
			} else {
				blnIsComplexCulture = true;
				iBidiLevel = culture.bidiLevel;
				iVerticalLineSpacer = culture.verticalLineSpacer;
				iFontIncrease = culture.fontIncrease;
			}			
		}
		
		public static function createLabel(in_tf:TextField, in_text:String):void {
			if (!blnWasInitalised) {
				Debugger.traceOut("Please initialise the Text Render before invoking its methods", Debugger.ERROR);
				return;
			}

			in_text = parseText(in_text);
			
			if (blnIsComplexCulture) {
				createComplexText(in_tf, in_text);
			} else {
				in_tf.height += 7;
				in_tf.text = in_text;
			}
		}
		
		
		/* PRIVATE */
		
		private static function createCultures():void 
		{
			arrComplexCultures = new Array;
			
			// add new cultures here
			// should be read from XML file
			arrComplexCultures.push(new TextCulture("ar-sa", 1, 5, 0));
			arrComplexCultures.push(new TextCulture("ka-ge", 0, 1, -1.5));
		}
		
		private static function parseText(in_text:String):String
		{
			in_text = in_text.split("\r\n").join("\n");
			return in_text;
		}
		
		private static function createComplexText(in_tf:TextField, in_text:String):void
		{
			// create the element format based on the existing TF
			var ef:ElementFormat = getElementFormat(in_tf);
			// create the textblock
			var tb:TextBlock = new TextBlock();
			// set bi di level
			tb.bidiLevel = iBidiLevel;
			// set the contents to the text + format
			tb.content = new TextElement(in_text, ef);
			
			var align:String = in_tf.getTextFormat().align;
			
			// if bidi level is odd and align is left set align to right
			if (tb.bidiLevel % 2 == 1 && align == TextFormatAlign.LEFT) {				
				align = TextFormatAlign.RIGHT;
			}
			
			
			var container:DisplayObjectContainer = in_tf.parent as DisplayObjectContainer;
			removePreviouslyCreatedLines(container);
			
			var s:Sprite = new Sprite();	
			s.name = RENDERED_LINE;
			s.mouseEnabled = false;
			s.mouseChildren = false;
			container.addChild(s);

			
			// need to clean the parent up first - i.e. if I have previously added text lines to it...
			//removePreviouslyCreatedLines(container);
			
			
			// create the lines
			createLines(s, tb, in_tf.x, in_tf.y, in_tf.width, align);
			
			in_tf.visible = false;
		}
		
		private static function removePreviouslyCreatedLines(container:DisplayObjectContainer):void
		{
			var i:int = container.numChildren;			
			while (i--) {
				if (container.getChildAt(i) is TextLine) {
					//&& tl.name == RENDERED_LINE
					container.removeChildAt(i);
				} else if(container.getChildAt(i) is Sprite) {
					var s:Sprite = container.getChildAt(i) as Sprite;
					if(s.name == RENDERED_LINE) {
						container.removeChildAt(i);
					}
				}
			}
		}
		
		private static function createLines(container:DisplayObjectContainer, textBlock:TextBlock, xPos:Number, yPos:Number, lineWidth:Number, align:String):void 
		{
			// create a line starting at the previous line (null, as non existant) and breaking at the width
			var textLine:TextLine = textBlock.createTextLine(null, lineWidth);			
			while (textLine)
			{
				// position the x 
				if (align == TextFormatAlign.CENTER) {
					// place this x at x location of the orig textfield + half its width minus half the textWidth of the new line
					textLine.x = (xPos + (lineWidth / 2)) - (textLine.textWidth / 2);
				} else if (align == TextFormatAlign.LEFT) {
					// place this x at x location of the orig textfield
					textLine.x = xPos;
				} else {
					// place this x at x location of the orig textfield + its width minus the textWidth of the new line
					textLine.x = (xPos + lineWidth) - textLine.textWidth;
				}
				
				// add the height of the text
				yPos += textLine.height;
				
				// if not the first line, add some space down
				if (textLine.previousLine != null) {
					yPos += iVerticalLineSpacer;
				} else {
					//add 12%
					// TODO - need to come up with a better solution here
					yPos += textLine.height * 0.12;
				}
				
				// position the y
				textLine.y = yPos;
				textLine.name = RENDERED_LINE;
				// add to sprite
				container.addChild(textLine);
				// create a line starting at the previous line (textLine) and breaking at the width
				textLine = textBlock.createTextLine(textLine, lineWidth);
			}
		}
		
		
		private static function getElementFormat(txt:TextField):ElementFormat 
		{
			// if there is no text - put some in as we cannot get format details of an empty textfield
			if (txt.text == "") {
				txt.text = "test text";
			}
			
			// get the tf from the textfield and use it to create the font desc and element format
			var tf:TextFormat = txt.getTextFormat();
			
			var fd:FontDescription = new FontDescription();
		    fd.fontName = tf.font;
		    fd.fontWeight = tf.bold ? flash.text.engine.FontWeight.BOLD : flash.text.engine.FontWeight.NORMAL;
		    fd.fontPosture = tf.italic ? flash.text.engine.FontPosture.ITALIC : flash.text.engine.FontPosture.NORMAL;
		    

		    var ef1:ElementFormat = new ElementFormat(fd);			
		    ef1.fontSize = tf.size as Number;
		    ef1.fontSize += iFontIncrease;
		    //ef1.color = new uint(0xFFFF00);
		    ef1.color = tf.color as uint;
		    ef1.alpha = 100;
		    ef1.kerning = tf.kerning ? flash.text.engine.Kerning.ON : flash.text.engine.Kerning.OFF;		    
		    

			//ef1.ligatureLevel = LigatureLevel.EXOTIC;
			
			return ef1;
		}		
		
		static public function get blnWasInitalised():Boolean { return _blnWasInitalised; }
	}
}